/* 异步线程缓冲区的设计*/
#pragma once

#include <cassert>
#include <iostream>
#include <string.h>
#include <vector>

namespace mylog {
//缓冲区默认大小（1MB）
const size_t default_buffer_size = 1 * 1024 * 1024;
//阈值
const size_t threshold = 2 * 1024 * 1024;
// 大于阈值以后每次扩容的自增值
const size_t increament = 1 * 1024 * 1024;

class Buffer {
  private:
    std::vector<char> _buffer; // 日志缓存区
    size_t _read_idx;          // 可读位置的起始下标
    size_t _write_idx;         // 可写位置的起始下标
  public:
    // 返回可写空间大小
    size_t WriteableSize() { return _buffer.size() - _write_idx; }
    // 返回可读空间大小
    size_t ReadableSize() { return _write_idx - _read_idx; }

  public:
    Buffer(size_t buffer_size = default_buffer_size): _buffer(buffer_size), _read_idx(0), _write_idx(0) {}
    ~Buffer(){_buffer.clear();}

  public:
    // 移动可读位置
    void MoveReadIdx(size_t len) {
        // 防止外界传入的参数不合法
        if (len > ReadableSize()) {
            _read_idx = ReadableSize();
        } else {
            _read_idx += len;
        }
    }

    // 移动可写位置
    void MoveWriteIdx(size_t len) {
        assert(_write_idx + len <= _buffer.size());
        _write_idx += len;
    }

    // 扩容
    void Resize(size_t len) {
        size_t new_size = (_buffer.size() < threshold)
                              ? _buffer.size() * 2 + len
                              : _buffer.size() + increament + len;
        _buffer.resize(new_size);
    }

    // 将数据放入缓冲区中
    inline void Push(const char* data, size_t len) {
        // 1. 判断空间是否足够
        if (len > WriteableSize()) Resize(len);
        // 2. 将数据写入缓冲区
        memcpy(&_buffer[_write_idx], data, len);
        // 3. 更新数据的写入位置
        MoveWriteIdx(len);
    }
    
    // 返回可读数据的起始地址
    const char* Start() { return &_buffer[_read_idx]; }
    // 数据判空
    bool Empty() { return _write_idx == _read_idx; }
    // 重置缓冲区
    void reset() {
        _write_idx = 0;
        _read_idx = 0;
    }

    // 交换缓冲区
    void swap(Buffer& buf) {
        std::swap(_write_idx, buf._write_idx);
        std::swap(_read_idx, buf._read_idx);
        _buffer.swap(buf._buffer);
    }
};
} // namespace mylog

/*------------------------------
#include <iostream>

void test_Buffer()() {
    mylog::Buffer buffer; // 使用默认大小创建一个 Buffer 对象
    char data[] = "Hello, World!";
    buffer.Push(data, strlen(data)); // 将数据放入缓冲区
    std::cout << "Readable size: " << buffer.ReadableSize() << std::endl;
    std::cout << "Start of readable data: " << buffer.Start() << std::endl;
    buffer.MoveReadIdx(5); // 移动可读位置
    std::cout << "Readable size after moving read index: "
              << buffer.ReadableSize() << std::endl;
    buffer.reset(); // 重置缓冲区
    std::cout << "Is buffer empty? " << buffer.Empty() << std::endl;
    return 0;
}
------------*/